#include "ogl/math/FrustumPlane.h"

using namespace Ogl;

bool Math::FrustumPlane::Create(const Math::Transform &transform, const Math::Frustum &frustum)
{
    const float aspect = frustum.aspect;
    const float fovY = glm::radians(frustum.fovy);
    const float zNear = frustum.nNear;
    const float zFar = frustum.nFar;

    const float halfVSide = zFar * tanf(fovY * .5f);
    const float halfHSide = halfVSide * aspect;

    const glm::vec3 camPos = transform.position;
    const glm::vec3 right = transform.GetRight();
    const glm::vec3 front = transform.GetForward();
    const glm::vec3 camUp = transform.GetUp();
    const glm::vec3 frontMultNear = zNear * front;
    ;
    const glm::vec3 frontMultFar = zFar * front;

    leftFace = {camPos, -glm::cross(camUp, frontMultFar + right * halfHSide)};
    rightFace = {camPos, -glm::cross(frontMultFar - right * halfHSide, camUp)};
    topFace = {camPos, -glm::cross(right, frontMultFar - camUp * halfVSide)};
    bottomFace = {camPos, -glm::cross(frontMultFar + camUp * halfVSide, right)};
    nearFace = {camPos + frontMultNear, front};
    farFace = {camPos + frontMultFar, -front};

    return true;
}

bool Math::FrustumPlane::Create(const Math::Transform &transform, const Math::Viewport &vp)
{

    const float halfVSide = (vp.top - vp.bottom) / 2.0f;
    const float halfHSide = (vp.right - vp.left) / 2.0f;
    const float zNear = vp.zNear;
    const float zFar = vp.zFar;

    const glm::vec3 camPos = transform.position;
    const glm::vec3 right = transform.GetRight();
    const glm::vec3 front = transform.GetForward();
    const glm::vec3 camUp = transform.GetUp();
    const glm::vec3 frontMultNear = zNear * front;
    ;
    const glm::vec3 frontMultFar = zFar * front;

    const glm::vec3 nearRightTop = camPos + frontMultNear + halfHSide * right + halfVSide * camUp;
    const glm::vec3 farLeftBottom = camPos + frontMultFar - halfHSide * right - halfVSide * camUp;

    FrustumPlane frustumPlane;

    frustumPlane.leftFace = {farLeftBottom, right};
    frustumPlane.rightFace = {nearRightTop, -right};
    frustumPlane.farFace = {farLeftBottom, -front};
    frustumPlane.nearFace = {nearRightTop, front};
    frustumPlane.topFace = {nearRightTop, -camUp};
    frustumPlane.bottomFace = {farLeftBottom, camUp};

    return true;
}